// ThreadObject.cpp: implementation of the ThreadObject class.
//
//////////////////////////////////////////////////////////////////////

//#include "stdafx.h"
#include "thread_object.h"

HT_NAMESPACE_BEGIN

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#ifdef _WIN32
ThreadObject::ThreadObject()
 : m_hThread(NULL), m_iThreadId(0), m_bUserBreak(false)
{
	
}

ThreadObject::~ThreadObject()
{
	if (NULL != m_hThread)
	{
		Cancel();
		CloseHandle(m_hThread);
		m_hThread = NULL;
	}
}

void ThreadObject::Run()
{

}

int ThreadObject::ThreadProc(void *arg)
{
	ThreadObject *pThis = (ThreadObject*)arg;
	pThis->Run();
	pThis->OnExit();
	CloseHandle(pThis->m_hThread);
	pThis->m_hThread = NULL;
	if (pThis->m_bAutoDelete)
	{
		delete pThis;
	}

	return 0;
}

int ThreadObject::StartThread(bool bAutoDelete)
{
	if (IsRuning())
		return false;

	m_bAutoDelete = bAutoDelete;
	m_bUserBreak = false;
	m_hThread = CreateThread(NULL, 0, 
		(LPTHREAD_START_ROUTINE)ThreadProc,
		this, CREATE_SUSPENDED, &m_iThreadId);
	ResumeThread(m_hThread);

	return true;
}

bool ThreadObject::IsRuning()
{
	return NULL != m_hThread;
}

void ThreadObject::OnExit()
{
	
}

bool ThreadObject::Wait(unsigned long Milli)
{
	if (NULL == m_hThread)
		return true;

	return (WaitForSingleObject(m_hThread, Milli) == WAIT_OBJECT_0);
}

bool ThreadObject::Cancel(unsigned long nWaitMilli)
{
	m_Mutex.enter();
	m_bUserBreak = true;
	m_Mutex.leave();

	if (0 == nWaitMilli)
		return true;

	return Wait(nWaitMilli);
}

void ThreadObject::KillThread ()
{
	if (NULL != m_hThread)
	{
		TerminateThread (m_hThread, 0);
		CloseHandle(m_hThread);
		m_hThread = NULL;
	}
}

bool ThreadObject::IsBreak ()
{
	HT_CS(m_Mutex);
	return m_bUserBreak;
}

#else
/******************************************************************************************************/
// LINUX Implement

#ifndef PTHREAD_STACK_MIN
#define PTHREAD_STACK_MIN 8192
#endif

ThreadObject::ThreadObject()
 : m_iThreadId(0), m_bUserBreak(false)
{
	
}

ThreadObject::~ThreadObject()
{
	if (0 != m_iThreadId)
	{
		Cancel();
		m_iThreadId = 0;
	}
}

void ThreadObject::Run()
{

}

void* ThreadObject::ThreadProc(void *arg)
{
	ThreadObject *pThis = (ThreadObject*)arg;
	pThis->Run();
	pThis->OnExit();
	HT_CS (pThis->m_Mutex);
	pThis->m_iThreadId = 0;
	if (pThis->m_bAutoDelete)
	{
		delete pThis;
	}

	return NULL;
}

int ThreadObject::StartThread(bool bAutoDelete)
{
	if (IsRuning())
		return false;

	HT_CS (m_Mutex);
	m_bAutoDelete = bAutoDelete;
	m_bUserBreak = false;
	
/*	
	m_hThread = CreateThread(NULL, 0, 
		(LPTHREAD_START_ROUTINE)ThreadProc,
		this, CREATE_SUSPENDED, &m_iThreadId);
	ResumeThread(m_hThread);
*/
	SYSCHECK(pthread_create(&m_iThreadId, NULL, ThreadProc, this)); 
    
	return true;
}

bool ThreadObject::IsRuning()
{
	HT_CS(m_Mutex);
	return 0 != m_iThreadId;
}

void ThreadObject::OnExit()
{
	
}

bool ThreadObject::Wait(unsigned long Milli)
{
	void* result;
	if (0 == m_iThreadId)
		return true;
	return (pthread_join(m_iThreadId, &result) == 0);
}

bool ThreadObject::Cancel(unsigned long nWaitMilli)
{
	m_Mutex.enter();
	m_bUserBreak = true;
	m_Mutex.leave();

	if (0 == nWaitMilli)
		return true;

	return Wait(nWaitMilli);
}

void ThreadObject::KillThread ()
{
	this->Cancel(INFINITE);
}

bool ThreadObject::IsBreak ()
{
	HT_CS(m_Mutex);
	return m_bUserBreak;
}
#endif // _WIN32

HT_NAMESPACE_END
